package com.infotop.controller;

import com.infotop.utils.ResponseBean;
import com.infotop.utils.Result;
import com.infotop.utils.ResultUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.pac4j.cas.client.rest.CasRestFormClient;
import org.pac4j.cas.profile.CasProfile;
import org.pac4j.cas.profile.CasRestProfile;
import org.pac4j.core.context.J2EContext;
import org.pac4j.core.credentials.TokenCredentials;
import org.pac4j.core.credentials.UsernamePasswordCredentials;
import org.pac4j.jwt.profile.JwtGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

@RestController
@CrossOrigin
public class WebController {
    @Autowired
    private JwtGenerator generator;

    @Autowired
    private CasRestFormClient casRestFormClient;

    @Value("${cas.serviceUrl}")
    private String serviceUrl;

    @Value("${cas.logoutUrl}")
    private String logoutUrl;

    final String STATUS_SUCCESS = "0";

    private static final Logger LOGGER = LogManager.getLogger(WebController.class);

    @RequestMapping(value = "/login")
    public Result login(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {

        try {

            J2EContext j2EContext = new J2EContext(request, response);

            final UsernamePasswordCredentials usernamePasswordCredentials = casRestFormClient.getCredentials(j2EContext);

            casRestFormClient.getAuthenticator();

            //TODO profile == null 用户名或密码 不正确，此处需要cas修改 明确返回信息
            final CasRestProfile profile = casRestFormClient.getUserProfile(usernamePasswordCredentials, j2EContext);

            if(profile == null){

                return ResultUtil.error(200,"用户名或密码错误！");
            }

            //获取ticket
            final TokenCredentials tokenCredentials = casRestFormClient.requestServiceTicket(serviceUrl, profile, j2EContext);
            //根据ticket获取用户信息
            final CasProfile casProfile = casRestFormClient.validateServiceTicket(serviceUrl, tokenCredentials, j2EContext);

            //生成jwt token
            String token = generator.generate(casProfile);

            Map<String, Object> map = new HashMap<>(2);

            map.put("token", token);

            //TODO 返回用户信息待确定
//            map.put("user", userMap);
            Result success = ResultUtil.success(map);
            return success;
        } catch (Exception e) {
            e.printStackTrace();
        }


        return ResultUtil.error(500,"异常");

    }


    @GetMapping("/article")
    public ResponseBean article() {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            return new ResponseBean(200, "You are already logged in", null);
        } else {
            return new ResponseBean(200, "You are guest", null);
        }
    }

    @GetMapping("/require_auth")
    @RequiresAuthentication
    public ResponseBean requireAuth() {
        return new ResponseBean(200, "You are authenticated", null);
    }

    @GetMapping("/require_role")
    @RequiresRoles("admin")
    public ResponseBean requireRole() {
        return new ResponseBean(200, "You are visiting require_role", null);
    }

    @GetMapping("/require_permission")
    @RequiresPermissions(logical = Logical.AND, value = {"view", "edit"})
    public ResponseBean requirePermission() {
        return new ResponseBean(200, "You are visiting permission require edit,view", null);
    }

    @RequestMapping(path = "/401")
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ResponseBean unauthorized() {
        return new ResponseBean(200, "Unauthorized", null);
    }
}
